Skip to content

feat: add UI tests for CookieBanner and configure vitest for React#132

Merged
ViktorSvertoka merged 1 commit into
developfrom
feature/test-cookie-banner
Jan 13, 2026
Merged

feat: add UI tests for CookieBanner and configure vitest for React#132
ViktorSvertoka merged 1 commit into
developfrom
feature/test-cookie-banner

Conversation

@AlinaRyabova
Copy link
Copy Markdown
Collaborator

@AlinaRyabova AlinaRyabova commented Jan 13, 2026

Summary by CodeRabbit

  • Tests

    • Added comprehensive test coverage for the cookie consent banner component, including validation of delayed appearance and acceptance functionality.
  • Chores

    • Updated testing framework configuration and dependencies to support test execution and monitoring.
    • Applied database schema improvements to enhance data integrity and query performance.

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 13, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit 2eda3da
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/6966397da9e9f700081c998d
😎 Deploy Preview https://deploy-preview-132--develop-devlovers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

This PR establishes frontend testing infrastructure by adding Vitest configuration, testing libraries, and a new CookieBanner component test suite. It also includes a database migration that adds a foreign key constraint and indexes to the quiz_attempts table.

Changes

Cohort / File(s) Summary
Test Configuration & Setup
frontend/package.json, frontend/vitest.config.ts
Added test scripts ("test", "test:ui", "test:run") and testing dependencies (@testing-library/react, @testing-library/dom, @testing-library/user-event, jsdom); updated vitest config to include component tests glob pattern and enable globals.
Component Tests
frontend/components/tests/CookieBanner.test.tsx
New test file for CookieBanner component covering delayed appearance (500ms) and acceptance flow with localStorage integration; uses mocked i18n, routing, and icons with fake timers.
Database Migration
frontend/drizzle/0014_steep_kabuki.sql
Adds foreign key constraint on quiz_attempts.user_id referencing users(id) with ON DELETE cascade, plus indexes on user_id and quiz_id.
Database Schema & Journal
frontend/drizzle/meta/0014_snapshot.json, frontend/drizzle/meta/_journal.json
Adds comprehensive PostgreSQL schema snapshot with all tables, indexes, foreign keys, and constraints; updates migration journal with new entry for migration version "7".

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Possibly related PRs

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰 A testing burrow, freshly dug,
With timers ticking, localStorage snug,
Quiz tables indexed, constraints aligned,
The schema snapshot, perfectly signed! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding UI tests for CookieBanner and configuring vitest for React testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @frontend/components/tests/CookieBanner.test.tsx:
- Around line 9-13: The hoisted vi.mock callback returns JSX but lacks the React
binding, causing failures under the mock's transform context; fix by importing
React into the test module scope (e.g., add import React from 'react' at the top
of the test) so the Link mock (the vi.mock(...) implementation that returns <a
href="#">{children}</a>) has React available for JSX, or alternatively rewrite
the mock to use React.createElement for the Link implementation.

In @frontend/vitest.config.ts:
- Around line 14-18: Update the Vitest test config so React component tests run
in a DOM-like environment: change the test configuration's environment property
in vitest.config.ts from 'node' to 'jsdom' (i.e., modify the test.environment
setting in the exported config object used by Vitest) so @testing-library/react
tests (e.g., CookieBanner) have access to document/window/localStorage.
🧹 Nitpick comments (4)
frontend/components/tests/CookieBanner.test.tsx (3)

1-3: Consider adding @testing-library/jest-dom for better assertions.

The test uses toBeDefined() and toBeNull() which work but are less expressive than jest-dom matchers like toBeInTheDocument(). Adding @testing-library/jest-dom provides more semantic DOM assertions.

♻️ Recommended setup
  1. Install the package:
npm install -D @testing-library/jest-dom
  1. Create a setup file (e.g., vitest.setup.ts):
import '@testing-library/jest-dom/vitest';
  1. Update vitest.config.ts:
test: {
  environment: 'jsdom',
  setupFiles: ['./vitest.setup.ts'],
  // ...
}

29-38: Strengthen assertions with more specific matchers.

toBeDefined() passes for any truthy value. Consider using toBeInTheDocument() (with jest-dom) or at minimum check the element content/role for stronger validation.

♻️ Suggested improvement
-    expect(screen.getByText('title')).toBeDefined();
+    expect(screen.getByText('title')).toBeVisible();

Or without jest-dom:

-    expect(screen.getByText('title')).toBeDefined();
+    const titleElement = screen.getByText('title');
+    expect(titleElement).toBeTruthy();
+    expect(titleElement.textContent).toBe('title');

40-52: Good test coverage for the accept flow.

The test properly verifies both the localStorage side effect and the UI state change after clicking accept.

Consider adding a test for the decline button to ensure complete coverage of the CookieBanner's interactive behavior.

📝 Additional test case suggestion
it('Click Decline -> Saves to LocalStorage -> Hides Banner', () => {
  render(<CookieBanner />);

  act(() => {
    vi.advanceTimersByTime(500);
  });

  const declineButton = screen.getByText('decline');
  fireEvent.click(declineButton);

  expect(localStorage.getItem('cookie-consent')).toBe('declined');
  expect(screen.queryByText('title')).toBeNull();
});
frontend/drizzle/0014_steep_kabuki.sql (1)

1-3: Verify no orphaned user_id records exist before migration.

Adding a foreign key constraint will fail if quiz_attempts.user_id contains values that don't exist in users.id. Ensure data integrity before running this migration in production.

Run this query against your database before applying the migration:

SELECT DISTINCT qa.user_id 
FROM quiz_attempts qa 
LEFT JOIN users u ON qa.user_id = u.id 
WHERE u.id IS NULL;

If any rows are returned, either:

  1. Delete the orphaned records, or
  2. Create placeholder user records

Also consider running the migration during low-traffic periods as creating indexes on large tables can lock the table temporarily.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c375a2 and 2eda3da.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • frontend/components/tests/CookieBanner.test.tsx
  • frontend/drizzle/0014_steep_kabuki.sql
  • frontend/drizzle/meta/0014_snapshot.json
  • frontend/drizzle/meta/_journal.json
  • frontend/package.json
  • frontend/vitest.config.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-30T16:01:02.523Z
Learnt from: kryvosheyin
Repo: DevLoversTeam/devlovers.net PR: 88
File: frontend/drizzle/schema.ts:153-153
Timestamp: 2025-12-30T16:01:02.523Z
Learning: The file frontend/drizzle/schema.ts is a legacy file not used by Drizzle or the runtime. The canonical schemas live in frontend/db/schema/* as configured in drizzle-config.ts, and that's what migrations and runtime use.

Applied to files:

  • frontend/drizzle/meta/0014_snapshot.json
🧬 Code graph analysis (2)
frontend/vitest.config.ts (1)
frontend/save-structure.cjs (1)
  • path (2-2)
frontend/components/tests/CookieBanner.test.tsx (1)
frontend/components/shared/CookieBanner.tsx (1)
  • CookieBanner (9-91)
🔇 Additional comments (5)
frontend/package.json (2)

16-19: LGTM! Test scripts are well-structured.

The test scripts follow standard Vitest conventions: test for watch mode, test:ui for the interactive UI, and test:run for CI/single-run execution.


57-59: Testing dependencies are appropriate for React 19.

The @testing-library/react v16.3.1 is compatible with React 19, and jsdom v27.4.0 provides the browser environment for component tests.

Also applies to: 67-67

frontend/vitest.config.ts (1)

16-16: Test include patterns look correct.

The glob patterns appropriately separate .test.ts for lib tests (node environment) and .test.tsx for component tests (DOM environment). However, if you need different environments for different test types, consider using Vitest's environmentMatchGlobs option.

If you need to keep node environment for lib/tests, you can configure per-pattern environments:

test: {
  environment: 'node',
  environmentMatchGlobs: [
    ['components/tests/**/*.test.tsx', 'jsdom'],
  ],
  include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
  globals: true,
},
frontend/drizzle/meta/_journal.json (1)

103-109: LGTM!

The journal entry correctly registers the new migration with the expected format and sequence.

frontend/drizzle/meta/0014_snapshot.json (1)

1-2333: LGTM! Auto-generated schema snapshot.

This snapshot is generated by Drizzle and correctly reflects the schema state after applying migration 0014. The new FK constraint and indexes on quiz_attempts are properly captured.

Comment on lines +9 to +13
vi.mock('@/i18n/routing', () => ({
Link: ({ children }: { children: React.ReactNode }) => (
<a href="#">{children}</a>
),
}));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add React import for JSX in the mock.

The Link mock returns JSX but doesn't import React. While React 17+ automatic JSX transform handles this in regular files, hoisted vi.mock calls may not have access to the transform context.

🐛 Proposed fix
+import React from 'react';
 import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
 import { render, screen, act, fireEvent } from '@testing-library/react';
 import { CookieBanner } from '@/components/shared/CookieBanner';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
vi.mock('@/i18n/routing', () => ({
Link: ({ children }: { children: React.ReactNode }) => (
<a href="#">{children}</a>
),
}));
import React from 'react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, act, fireEvent } from '@testing-library/react';
import { CookieBanner } from '@/components/shared/CookieBanner';
vi.mock('@/i18n/routing', () => ({
Link: ({ children }: { children: React.ReactNode }) => (
<a href="#">{children}</a>
),
}));
🤖 Prompt for AI Agents
In @frontend/components/tests/CookieBanner.test.tsx around lines 9 - 13, The
hoisted vi.mock callback returns JSX but lacks the React binding, causing
failures under the mock's transform context; fix by importing React into the
test module scope (e.g., add import React from 'react' at the top of the test)
so the Link mock (the vi.mock(...) implementation that returns <a
href="#">{children}</a>) has React available for JSX, or alternatively rewrite
the mock to use React.createElement for the Link implementation.

Comment thread frontend/vitest.config.ts
Comment on lines 14 to 18
test: {
environment: "node",
include: ["lib/tests/**/*.test.ts"],
environment: 'node',
include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
globals: true,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Environment should be jsdom for React component tests.

The test environment is set to 'node', but the CookieBanner tests use @testing-library/react which requires DOM APIs (document, window, localStorage). Since jsdom is already added as a devDependency, update the environment accordingly.

🐛 Proposed fix
   test: {
-    environment: 'node',
+    environment: 'jsdom',
     include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
     globals: true,
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test: {
environment: "node",
include: ["lib/tests/**/*.test.ts"],
environment: 'node',
include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
globals: true,
},
test: {
environment: 'jsdom',
include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
globals: true,
},
🤖 Prompt for AI Agents
In @frontend/vitest.config.ts around lines 14 - 18, Update the Vitest test
config so React component tests run in a DOM-like environment: change the test
configuration's environment property in vitest.config.ts from 'node' to 'jsdom'
(i.e., modify the test.environment setting in the exported config object used by
Vitest) so @testing-library/react tests (e.g., CookieBanner) have access to
document/window/localStorage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants